﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App1AppHandler;
using Reborn_WorldServer;

namespace Reborn_Server.App1AppHandler
{
    public class TargetSpell : Spell
    {
        //Casting creature
        //public CreatureBase MyCreatureBase;
        public long CastingCreatureGUID = -1;
        public int CastingCharacterID = -1;
        public int CastingCreatureInt = 0;
        public int CastingCreatureWis = 0;
        public int CastingCreatureLevel = 1;

        //Casting creatures target
        public CreatureBase TargetCreatureBase;

        public TargetSpell() { }

        protected virtual bool InitializeInstantCast(CreatureBase myCreatureBase, CreatureBase _targetCreatureBase, SpellIcon sIcon, int CastLevel, bool sendMessages)
        {
            //Set reference to casting creature
            if (myCreatureBase is Character)
                CastingCharacterID = myCreatureBase.ID;
            else if (myCreatureBase is Creature)
                CastingCreatureGUID = myCreatureBase.CreatureID;

            CastingCreatureInt = myCreatureBase.IntelligenceTotal;
            CastingCreatureWis = myCreatureBase.WisdomTotal;
            CastingCreatureLevel = CastLevel;

            spellIcon = sIcon;

            TargetCreatureBase = _targetCreatureBase;

            //Set spell Id
            SpellID = Managers.GameHandler.ItemIDGen.GetSpellID();

            if (spellIcon.Offensive == true && TargetCreatureBase is Creature)
                TargetCreatureBase.hateManager.UpdateList(myCreatureBase, 0);

            //Get the creature we would give a SD flag to.
            Character characterToApplyFlag = null;

            //If the creature we're casting at is a pet, get its master
            Pet_Controller pc = TargetCreatureBase.petController;
            //Has pet controller, check if master is character
            if (pc != null && pc.MasterCreature is Character)
                characterToApplyFlag = (Character)pc.MasterCreature;
            //No pet controller, check if target is character
            else if (pc == null && TargetCreatureBase is Character)
                characterToApplyFlag = (Character)TargetCreatureBase;

            //If we're attacking a player, and we dont have a flag on them, give them a flag on us.
            if (characterToApplyFlag != null &&
                myCreatureBase is Character &&
                characterToApplyFlag != myCreatureBase &&
                myCreatureBase.hateManager.GetCreatureHateInfo(characterToApplyFlag) == null &&
                spellIcon.Offensive == true)
            {
                Character charToAttack = (Character)characterToApplyFlag;
                if (charToAttack.friendsManager.hasNoSDFlag(CastingCharacterID) == false)
                {
                    if (charToAttack.hateManager.GetCreatureHateInfo(myCreatureBase) == null)
                    {
                        charToAttack.SendMessage("You have been ATTACKED by " + myCreatureBase.Name + "!", "damaged");
                        charToAttack.PlaySound("Ding", charToAttack.MapX, charToAttack.MapY);

                        charToAttack.hateManager.UpdateList(myCreatureBase, 0);


                        charToAttack.AddMapItem(myCreatureBase.currentMapItem);
                    }
                    else
                        charToAttack.hateManager.UpdateList(myCreatureBase, 0);
                }
            }

            if (TargetCreatureBase is Creature)
            {
                Creature targetCrit = (Creature)TargetCreatureBase;
                if (targetCrit.isImmune(spellIcon) == true)
                {
                    myCreatureBase.SendMessage(TargetCreatureBase.Name + " is immune to " + spellIcon.Name + "!", "spelldefense");
                    return false;
                }
            }
            if (tryResist(spellIcon, CastLevel, CastingCreatureInt, CastingCreatureWis, TargetCreatureBase) == true)
            {
                if (myCreatureBase != TargetCreatureBase)
                    myCreatureBase.SendMessage(TargetCreatureBase.Name + " resists " + spellIcon.Name + "!", "spelldefense");

                TargetCreatureBase.SendMessage("You resist " + myCreatureBase.Name + "'s " + spellIcon.Name + "!", "spelloffense");
                return false;
            }

            //Send out messages
            if (sendMessages == true)
            {
                if (TargetCreatureBase is Character)
                {
                    Character character = (Character)TargetCreatureBase;
                    if (TargetCreatureBase.CreatureID != myCreatureBase.CreatureID)
                    {
                        Message msg = new Message();

                        if (spellIcon.Offensive == true)
                            msg.Type = "spelloffense";
                        else
                            msg.Type = "spelldefense";

                        msg.CreatureID = TargetCreatureBase.CreatureID;
                        msg.Text = myCreatureBase.Name + " casts " + base.spellIcon.Name + " on you";
                        character.AddMessage(msg);
                    }
                }
                if (myCreatureBase is Character)
                {
                    Character character = (Character)myCreatureBase;

                    Message msg = new Message();

                    if (spellIcon.Offensive == true)
                        msg.Type = "spelloffense";
                    else
                        msg.Type = "spelldefense";

                    msg.CreatureID = TargetCreatureBase.CreatureID;
                    msg.Text = "You cast " + base.spellIcon.Name + " on " + TargetCreatureBase.Name;
                    character.AddMessage(msg);
                }
            }

            return true;
        }

        protected virtual bool InitializeCast(CreatureBase myCreatureBase, int CastLevel, long CreatureGUID, bool sendMessages, out List<MapItem> MapItemsWithin12)
        {
            MapItemsWithin12 = new List<MapItem>();

            //Set reference to casting creature
            if (myCreatureBase is Character)
                CastingCharacterID = myCreatureBase.ID;
            else if (myCreatureBase is Creature)
                CastingCreatureGUID = myCreatureBase.CreatureID;

            CastingCreatureInt = myCreatureBase.IntelligenceTotal;
            CastingCreatureWis = myCreatureBase.WisdomTotal;
            CastingCreatureLevel = CastLevel;

            //Get Spell Icon For this spell
            if (myCreatureBase.WarmSpell == null)
            {
                if (myCreatureBase is Character)
                {
                    Character character = (Character)myCreatureBase;

                    Message message = new Message();
                    message.CreatureID = character.CreatureID;
                    message.Type = "server";
                    message.Text = "Server: Spell is not ready";
                    character.AddMessage(message);

                    character.PlaySound("Ding", character.MapX, character.MapY);

                    character.SetBusy(false);
                }

                return false;
            }
            else
            {
                //Set reference to this spells Icon
                spellIcon = myCreatureBase.WarmSpell;
            }
            //Make sure spell being casted is this spell
            if (spellIcon.ClassName != this.GetType().Name)
            {
                if (myCreatureBase is Character)
                {
                    Character character = (Character)myCreatureBase;

                    Message message = new Message();
                    message.CreatureID = character.CreatureID;
                    message.Type = "server";
                    message.Text = "Server: Spell is not ready";
                    character.AddMessage(message);

                    character.PlaySound("Ding", character.MapX, character.MapY);

                    character.SetBusy(false);
                }
                return false;
            }
            //Make sure we have enough mana
            if (myCreatureBase.Mana < spellIcon.ManaCost)
            {
                myCreatureBase.WarmSpell = null;

                if (myCreatureBase is Character)
                {
                    Character character = (Character)myCreatureBase;
                    character.Update_Character();

                    Message message = new Message();
                    message.Type = "server";
                    message.CreatureID = myCreatureBase.CreatureID;
                    message.Text = "Server: Not enough mana";

                    character.AddMessage(message);
                    character.PlaySound("Ding", character.MapX, character.MapY);

                    character.SetBusy(false);
                }
                return false;
            }
            //Get Current Map
            //Map CurrentMap = myCreatureBase.GameHandler.GetMap(myCreatureBase.MapID, myCreatureBase.Instance);

            //Get target creature
            CreatureBase targetCreatureBase = null;
            foreach (MapItem mapitem in myCreatureBase.currentMapItem.mapItemsWithin12)
            {
                if (Math.Abs(mapitem.MapX - myCreatureBase.MapX) <= 4 && Math.Abs(mapitem.MapY - myCreatureBase.MapY) <= 4)
                {
                    foreach (CreatureBase creaturebase in mapitem.CreaturesBases)
                    {
                        if (creaturebase.CreatureID == CreatureGUID)
                        {
                            targetCreatureBase = creaturebase;
                            break;
                        }
                    }
                }
                if (Math.Abs(mapitem.MapX - myCreatureBase.MapX) <= 12 && Math.Abs(mapitem.MapY - myCreatureBase.MapY) <= 12)
                {
                    MapItemsWithin12.Add(mapitem);
                }
            }
            if (targetCreatureBase == null || targetCreatureBase.HP < 1)
            {
                if (myCreatureBase is Character)
                {
                    Character character = (Character)myCreatureBase;

                    Message message = new Message();
                    message.CreatureID = character.CreatureID;
                    message.Type = "server";
                    message.Text = "Server: Cannot find target creature";
                    character.AddMessage(message);

                    character.PlaySound("Ding", character.MapX, character.MapY);

                    character.SetBusy(false);
                }
                return false;
            }
            //Set Target Creature Reference
            TargetCreatureBase = targetCreatureBase;

            //Generate Unique Spell ID
            SpellID = myCreatureBase.GameHandler.ItemIDGen.GetSpellID();

            //Reduce mana and remove warm spell
            myCreatureBase.Mana = myCreatureBase.Mana - spellIcon.ManaCost;
            //Update CreatureBase Mana
            foreach (MapItem mapitem in MapItemsWithin12)
            {
                if (Math.Abs(mapitem.MapX - myCreatureBase.MapX) <= 4 && Math.Abs(mapitem.MapY - myCreatureBase.MapY) <= 4)
                {
                    foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                    {
                        if (creatureBase is Character)
                        {
                            Character chartoupdate = (Character)creatureBase;
                            chartoupdate.UpdateCreatureBaseMana(myCreatureBase);
                        }
                    }
                }
            }
            myCreatureBase.WarmSpell = null;

            Buff invis = myCreatureBase.buffManager.GetBuff("Invisibility");
            if (invis != null) invis.RemoveSpell(true, true);

            if (spellIcon.Skill != "Shadow")
            {
                Buff hideBuff = myCreatureBase.buffManager.GetBuffByStackType("Hide");
                if (hideBuff != null) hideBuff.RemoveSpell(true, true);
            }

            //Update Character
            myCreatureBase.Update_Character();

            //Grant Skill for this cast and start round timer
            if (myCreatureBase is Character)
            {
                Character character = (Character)myCreatureBase;

                //character.Timer_Round_Interval = 3000 + (3000 * (character.CastingSpeedPercentModifier / 100.00));
                character.Timer_Round_Interval = 1500; // +(1500.00 * (character.CastingSpeedPercentModifier / 100.00));
                character.Timer_Round_Start();
            }

            if (spellIcon.Offensive == true && TargetCreatureBase is Creature)
                TargetCreatureBase.hateManager.UpdateList(myCreatureBase, 0);


            //Get the creature we would give a SD flag to.
            Character characterToApplyFlag = null;

            //If the creature we're casting at is a pet, get its master
            Pet_Controller pc = TargetCreatureBase.petController;
            //Has pet controller, check if master is character
            if (pc != null && pc.MasterCreature is Character)
                characterToApplyFlag = (Character)pc.MasterCreature;
            //No pet controller, check if target is character
            else if (pc == null && TargetCreatureBase is Character)
                characterToApplyFlag = (Character)TargetCreatureBase;

            //If we're attacking a player, and we dont have a flag on them, give them a flag on us.
            if (characterToApplyFlag != null && 
                myCreatureBase is Character &&
                characterToApplyFlag != myCreatureBase &&
                myCreatureBase.hateManager.GetCreatureHateInfo(characterToApplyFlag) == null && 
                spellIcon.Offensive == true)
            {
                Character charToAttack = (Character)characterToApplyFlag;
                if (charToAttack.friendsManager.hasNoSDFlag(CastingCharacterID) == false)
                {
                    if (charToAttack.hateManager.GetCreatureHateInfo(myCreatureBase) == null)
                    {
                        charToAttack.SendMessage("You have been ATTACKED by " + myCreatureBase.Name + "!", "damaged");
                        charToAttack.PlaySound("Ding", charToAttack.MapX, charToAttack.MapY);

                        charToAttack.hateManager.UpdateList(myCreatureBase, 0);


                        charToAttack.AddMapItem(myCreatureBase.currentMapItem);
                    }
                    else
                        charToAttack.hateManager.UpdateList(myCreatureBase, 0);
                }
            }

            if (TargetCreatureBase is Creature)
            {
                Creature targetCrit = (Creature)TargetCreatureBase;
                if (targetCrit.isImmune(spellIcon) == true)
                {
                    myCreatureBase.SendMessage(TargetCreatureBase.Name + " is immune to " + spellIcon.Name + "!", "spelldefense");
                    return false;
                }
            }
            if (tryResist(spellIcon, CastLevel, CastingCreatureInt, CastingCreatureWis, TargetCreatureBase) == true)
            {
                if (myCreatureBase != TargetCreatureBase)
                    myCreatureBase.SendMessage(TargetCreatureBase.Name + " resists " + spellIcon.Name + "!", "spelldefense");
                
                TargetCreatureBase.SendMessage("You resist " + myCreatureBase.Name + "'s " + spellIcon.Name + "!", "spelloffense");
                return false;
            }


            //Grant Skill for this cast and start round timer
            if (myCreatureBase is Character)
            {
                Character character = (Character)myCreatureBase;

                Decimal expToAdd = System.Convert.ToDecimal(3.00 + (3.00 * (character.CastingSpeedPercentModifier / 100.00)));
                expToAdd = expToAdd + 1.5M;

                character.skillManager.AddExp(spellIcon.Skill, expToAdd);
            }

            //Send out messages
            if (sendMessages == true)
            {
                if (TargetCreatureBase is Character)
                {
                    Character character = (Character)TargetCreatureBase;
                    if (TargetCreatureBase.CreatureID != myCreatureBase.CreatureID)
                    {
                        Message msg = new Message();

                        if (spellIcon.Offensive == true)
                            msg.Type = "spelloffense";
                        else
                            msg.Type = "spelldefense";

                        msg.CreatureID = targetCreatureBase.CreatureID;
                        msg.Text = myCreatureBase.Name + " casts " + base.spellIcon.Name + " on you";
                        character.AddMessage(msg);
                    }
                }
                if (myCreatureBase is Character)
                {
                    Character character = (Character)myCreatureBase;

                    Message msg = new Message();

                    if (spellIcon.Offensive == true)
                        msg.Type = "spelloffense";
                    else
                        msg.Type = "spelldefense";

                    msg.CreatureID = targetCreatureBase.CreatureID;
                    msg.Text = "You cast " + base.spellIcon.Name + " on " + TargetCreatureBase.Name;
                    character.AddMessage(msg);
                }
            }
            return true;
        }

        //This will be overriden in the subclass if the spell can be totally resisted
        virtual public bool tryResist(SpellIcon _spellIcon, int castLevel, int castInt, int castWis, CreatureBase targetCreatureBase)
        {
            return false;
        }
    }
}
